<template>
  <Query
    ref="queryRef"
    :query="schema.query"
    :querys="schema.querys"
    @query="queryEvent"
    @reset="reset"
  />

  <el-row type="flex" justify="space-between" align="middle" style="margin: 10px 0">
    <div>
      <el-space>
        <template v-if="showQuery">
          <el-button type="primary" @click="queryEvent">查询</el-button>
          <el-button @click="reset">重置</el-button>
        </template>
      </el-space>
    </div>
    <div>
      <Body :body="schema.tableTop" />
    </div>
  </el-row>
  <vxe-table style="margin-top: 10px" :data="lowCodeTableData" v-bind="attr" :loading="loading">
    <Column v-for="(column, index) in columns" :key="index" :column="column" />
  </vxe-table>
  <vxe-pager
    v-if="hasPaper"
    style="margin-top: 10px"
    v-bind="pagerConfig"
    @page-change="pageChange"
  ></vxe-pager>
</template>

<script setup>
import { ref, getCurrentInstance, provide, onMounted, computed, watchEffect } from 'vue'
import { isDef } from '@/utils/index'
import { handleApi } from '../../common/api'
import { filterAttrByExclude } from '../../common/util'
import Body from '../body/index.vue'
import Column from './column.vue'
import Query from './query.vue'

defineOptions({ name: 'CrudCom' })

const instance = getCurrentInstance()

let formFn = null
const task = []

provide('lowCodeCrud', {
  refreshTable,
  setForm: (_formFn) => {
    formFn = _formFn
    task.forEach((item) => {
      item()
    })
    task.length = 0
  }
})

const props = defineProps({
  schema: {
    type: Object,
    required: true
  }
})

const lowCodeTableData = ref([])
const loading = ref(false)
const pagerConfig = ref({
  currentPage: 1,
  pageSize: 10,
  total: 0,
  layouts: [
    'PrevJump',
    'PrevPage',
    'Jump',
    'PageCount',
    'NextPage',
    'NextJump',
    'Sizes',
    'Total',
    'FullJump'
  ]
})

const queryRef = ref()
const schema = props.schema
const showQuery = computed(() => {
  return schema.querys && schema.querys.length
})

const autoRequest = isDef(schema.autoRequest) ? schema.autoRequest : true
const pageField = schema.pageField || 'pageNum'
const pageSizeField = schema.pageField || 'pageSize'
const api = schema.api
const columns = ref([])
const attr = filterAttrByExclude(
  ['pageField', 'pageSizeField', 'autoRequest', 'hasPaper', 'querys', 'onMounted'],
  schema
)
const schemaPaper = schema.hasPaper
const hasPaper = ref(isDef(schemaPaper) ? schemaPaper : true)

watchEffect(() => {
  columns.value = props.schema.columns || []
})

function requestApi(extra) {
  const obj = {
    [pageField]: pagerConfig.value.currentPage,
    [pageSizeField]: pagerConfig.value.pageSize,
    ...extra
  }
  if (isDef(schemaPaper) && !schemaPaper) {
    delete obj.page
    delete obj.size
  }
  if (!api) {
    return
  }
  loading.value = true
  handleApi(api, instance, obj)
    .then((data) => {
      if (isDef(schema.hasPaper) && !schema.hasPaper) {
        lowCodeTableData.value = data
      } else {
        const total = Number(data.total)
        lowCodeTableData.value = data.rows
        pagerConfig.value.total = total
        hasPaper.value = !!total
      }
    })
    .finally(() => {
      loading.value = false
    })
}

function pageChange({ type, currentPage, pageSize }) {
  if (type === 'current') {
    pagerConfig.value.currentPage = currentPage
    pagerConfig.value.pageSize = pageSize
  }
  requestApi()
}

function queryEvent() {
  if (!formFn) {
    task.push(() => {
      requestApi(formFn.getFieldsValue())
    })
  } else {
    requestApi(formFn.getFieldsValue())
  }
}

function reset() {
  pagerConfig.value.currentPage = 1
  formFn.resetFields()
  requestApi(formFn.getFieldsValue())
}

function refreshTable() {
  pagerConfig.value.currentPage = 1
  queryEvent()
}

function excuteQueryFn(fnName, ...args) {
  if (formFn) {
    formFn[fnName](...args)
  } else {
    task.push(() => {
      formFn[fnName](...args)
    })
  }
}

onMounted(() => {
  if (autoRequest) {
    queryEvent()
  }
  if (schema.onMounted) {
    schema.onMounted({
      instance
    })
  }
})
</script>
